home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xearth-0.92 / xearth.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  22KB  |  956 lines

  1. /*
  2.  * xearth.c
  3.  * kirk johnson
  4.  * july 1993
  5.  *
  6.  * RCS $Id: xearth.c,v 1.14 1994/05/25 06:04:04 tuna Exp $
  7.  *
  8.  * Copyright (C) 1989, 1990, 1993, 1994 Kirk Lauritz Johnson
  9.  *
  10.  * Parts of the source code (as marked) are:
  11.  *   Copyright (C) 1989, 1990, 1991 by Jim Frost
  12.  *   Copyright (C) 1992 by Jamie Zawinski <jwz@lucid.com>
  13.  *
  14.  * Permission to use, copy, modify, distribute, and sell this
  15.  * software and its documentation for any purpose is hereby granted
  16.  * without fee, provided that the above copyright notice appear in
  17.  * all copies and that both that copyright notice and this
  18.  * permission notice appear in supporting documentation. The author
  19.  * makes no representations about the suitability of this software
  20.  * for any purpose. It is provided "as is" without express or
  21.  * implied warranty.
  22.  *
  23.  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  24.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  25.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT
  26.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  27.  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  28.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  29.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  30.  */
  31. #include "xearth.h"
  32. #include "kljcpyrt.h"
  33.  
  34. #ifndef NO_SETPRIORITY
  35. /* apparently some systems (possibly mt.xinu 4.3bsd?) may need 
  36.  * <sys/time.h> to be included here before <sys/resource.h>.
  37.  */
  38. #include <sys/resource.h>    /* for setpriority() */
  39. #endif
  40.  
  41. #define ModeX   (0)             /* possible output_mode values */
  42. #define ModePPM (1)
  43. #define ModeGIF (2)
  44.  
  45. void set_priority();
  46. void output();
  47. void compute_positions();
  48. void sun_relative_position();
  49. void simple_orbit();
  50. void set_defaults();
  51. int  using_x();
  52. void command_line();
  53.  
  54. char    *progname;              /* program name                */
  55. int      output_mode;           /* output mode (X, PPM, ...)   */
  56. double   view_lon;              /* viewing position longitude  */
  57. double   view_lat;              /* viewing position latitude   */
  58. int      view_pos_type;        /* type of viewing position    */
  59. double   sun_rel_lon;        /* view lon, relative to sun   */
  60. double   sun_rel_lat;        /* view lat, relative to sun   */
  61. double   orbit_period;        /* orbit period (seconds)      */
  62. double   orbit_inclin;        /* orbit inclination (degrees) */
  63. double   view_mag;        /* viewing magnification       */
  64. int      do_shade;        /* render with shading?        */
  65. double   sun_lon;               /* sun position longitude      */
  66. double   sun_lat;               /* sun position latitude       */
  67. int      compute_sun_pos;       /* compute sun's position?     */
  68. int      wdth;                  /* image width (pixels)        */
  69. int      hght;                  /* image height (pixels)       */
  70. int      shift_x;        /* image shift (x, pixels)     */
  71. int      shift_y;        /* image shift (y, pixels)     */
  72. int      do_stars;        /* show stars in background?   */
  73. double   star_freq;        /* frequency of stars          */
  74. int      do_grid;        /* show lon/lat grid?          */
  75. int      grid_big;        /* lon/lat grid line spacing   */
  76. int      grid_small;        /* dot spacing along grids     */
  77. int      do_label;              /* label image                 */
  78. int      do_markers;        /* display markers (X only)    */
  79. int      wait_time;             /* wait time between redraw    */
  80. double   time_warp;        /* passage of time multiplier  */
  81. int      fixed_time;        /* fixed viewing time (ssue)   */
  82. int      day;                   /* day side brightness (%)     */
  83. int      night;                 /* night side brightness (%)   */
  84. double   xgamma;        /* gamma correction (X only)   */
  85. int      use_two_pixmaps;    /* use two pixmaps? (X only)   */
  86. int      num_colors;        /* number of colors to use     */
  87. int      do_fork;        /* fork child process?         */
  88. int      priority;        /* desired process priority    */
  89.  
  90. time_t start_time = 0;
  91. time_t current_time;
  92.  
  93.  
  94. int main(argc, argv)
  95.      int   argc;
  96.      char *argv[];
  97. {
  98.   set_defaults();
  99.  
  100.   if (using_x(argc, argv))
  101.     command_line_x(argc, argv);
  102.   else
  103.     command_line(argc, argv);
  104.  
  105.   if (priority != 0)
  106.     set_priority(priority);
  107.  
  108.   output();
  109.  
  110.   exit(0);
  111. }
  112.  
  113.  
  114. #ifdef NO_SETPRIORITY
  115.  
  116. /* setpriority()-like functionality for System V
  117.  * derivates that only provide nice()
  118.  */
  119. void set_priority(new)
  120.      int new;
  121. {
  122.   int old;
  123.   extern int errno;
  124.  
  125.   /* determine current priority of the process
  126.    */
  127.   errno = 0;
  128.   old   = nice(0);
  129.   if ((old == -1) && (errno != 0))
  130.   {
  131.     perror("nice");
  132.     exit(-1);
  133.   }
  134.  
  135.   /* try to change priority to new
  136.    */
  137.   new = nice(new - old);
  138.   if ((new == -1) && (errno != 0))
  139.   {
  140.     perror("nice");
  141.     exit(-1);
  142.   }
  143. }
  144.  
  145. #else /* NO_SETPRIORITY */
  146.  
  147. /* for systems that provide setpriority(),
  148.  * set_priority() is just a wrapper
  149.  */
  150. void set_priority(new)
  151.      int new;
  152. {
  153.   if ((setpriority(PRIO_PROCESS, getpid(), new) == -1))
  154.   {
  155.     perror("setpriority");
  156.     exit(-1);
  157.   }
  158. }
  159.  
  160. #endif /* NO_SETPRIORITY */
  161.  
  162.  
  163. void output()
  164. {
  165.   void (*render)();
  166.  
  167.   if (do_shade)
  168.     render = render_with_shading;
  169.   else
  170.     render = render_no_shading;
  171.  
  172.   switch (output_mode)
  173.   {
  174.   case ModePPM:
  175.     compute_positions();
  176.     scan_map();
  177.     do_dots();
  178.     ppm_setup(stdout);
  179.     render(ppm_row);
  180.     break;
  181.  
  182.   case ModeGIF:
  183.     compute_positions();
  184.     scan_map();
  185.     do_dots();
  186.     gif_setup(stdout);
  187.     render(gif_row);
  188.     gif_cleanup();
  189.     break;
  190.  
  191.   case ModeX:
  192.     if ((!do_fork) || (fork() == 0))
  193.     {
  194.       while (1)
  195.       {
  196.     compute_positions();
  197.  
  198.     /* should only do this if position has changed ... */
  199.     scan_map();
  200.     do_dots();
  201.  
  202.         x11_setup();
  203.         render(x11_row);
  204.         x11_cleanup();
  205.         sleep((unsigned) wait_time);
  206.       }
  207.     }
  208.     break;
  209.  
  210.   default:
  211.     assert(0);
  212.   }
  213. }
  214.  
  215.  
  216. void compute_positions()
  217. {
  218.   /* determine "current" time
  219.    */
  220.   if (fixed_time == 0)
  221.   {
  222.     current_time = time(NULL);
  223.     if (start_time == 0)
  224.       start_time = current_time;
  225.     else
  226.       current_time = start_time + (current_time - start_time) * time_warp;
  227.   }
  228.   else
  229.   {
  230.     current_time = fixed_time;
  231.   }
  232.  
  233.   /* determine position on earth's surface where sun is directly
  234.    * overhead
  235.    */
  236.   if (compute_sun_pos)
  237.     sun_position(current_time, &sun_lat, &sun_lon);
  238.  
  239.   /* determine viewing position
  240.    */
  241.   if (view_pos_type == ViewPosTypeSun)
  242.   {
  243.     sun_relative_position(&view_lat, &view_lon);
  244.   }
  245.   else if (view_pos_type == ViewPosTypeOrbit)
  246.   {
  247.     simple_orbit(current_time, &view_lat, &view_lon);
  248.   }
  249. }
  250.  
  251.  
  252. void sun_relative_position(lat_ret, lon_ret)
  253.      double *lat_ret;        /* (return) latitude  */
  254.      double *lon_ret;        /* (return) longitude */
  255. {
  256.   double lat, lon;
  257.  
  258.   lat = sun_lat + sun_rel_lat;
  259.   lon = sun_lon + sun_rel_lon;
  260.  
  261.   /* sanity check */
  262.   assert((lat >= -180) && (lat <= 180));
  263.   assert((lon >= -360) && (lon <= 360));
  264.  
  265.   if (lat > 90)
  266.   {
  267.     lat  = 180 - lat;
  268.     lon += 180;
  269.   }
  270.   else if (lat < -90)
  271.   {
  272.     lat  = -180 - lat;
  273.     lon += 180;
  274.   }
  275.  
  276.   if (lon > 180)
  277.   {
  278.     do
  279.       lon -= 360;
  280.     while (lon > 180);
  281.   }
  282.   else if (lon < -180)
  283.   {
  284.     do
  285.       lon += 360;
  286.     while (lon < -180);
  287.   }
  288.  
  289.   *lat_ret = lat;
  290.   *lon_ret = lon;
  291. }
  292.  
  293.  
  294. void simple_orbit(ssue, lat, lon)
  295.      time_t  ssue;        /* seconds since unix epoch */
  296.      double *lat;        /* (return) latitude        */
  297.      double *lon;        /* (return) longitude       */
  298. {
  299.   double x, y, z;
  300.   double a, c, s;
  301.   double t1, t2;
  302.  
  303.   /* start at 0 N 0 E */
  304.   x = 0;
  305.   y = 0;
  306.   z = 1;
  307.  
  308.   /* rotate in about y axis (from z towards x) according to the number
  309.    * of orbits we've completed
  310.    */
  311.   a  = ((double) ssue / orbit_period) * (2*M_PI);
  312.   c  = cos(a);
  313.   s  = sin(a);
  314.   t1 = c*z - s*x;
  315.   t2 = s*z + c*x;
  316.   z  = t1;
  317.   x  = t2;
  318.  
  319.   /* rotate about z axis (from x towards y) according to the
  320.    * inclination of the orbit
  321.    */
  322.   a  = orbit_inclin * (M_PI/180);
  323.   c  = cos(a);
  324.   s  = sin(a);
  325.   t1 = c*x - s*y;
  326.   t2 = s*x + c*y;
  327.   x  = t1;
  328.   y  = t2;
  329.  
  330.   /* rotate about y axis (from x towards z) according to the number of
  331.    * rotations the earth has made
  332.    */
  333.   a  = ((double) ssue / EarthPeriod) * (2*M_PI);
  334.   c  = cos(a);
  335.   s  = sin(a);
  336.   t1 = c*x - s*z;
  337.   t2 = s*x + c*z;
  338.   x  = t1;
  339.   z  = t2;
  340.  
  341.   *lat = asin(y) * (180/M_PI);
  342.   *lon = atan2(x, z) * (180/M_PI);
  343. }
  344.  
  345.  
  346. /* look through the command line arguments to figure out if we're
  347.  * using X or not (if either of the "-ppm" or "-gif" arguments is
  348.  * found, we're not using X, otherwise we are).
  349.  */
  350. int using_x(argc, argv)
  351.      int   argc;
  352.      char *argv[];
  353. {
  354.   int i;
  355.  
  356.   /* loop through the args, break if we find "-ppm" or "-gif"
  357.    */
  358.   for (i=1; i<argc; i++)
  359.     if ((strcmp(argv[i], "-ppm") == 0) ||
  360.     (strcmp(argv[i], "-gif") == 0))
  361.       break;
  362.  
  363.   /* if we made it through the loop without finding "-ppm" or "-gif"
  364.    * (and breaking out), assume we're using X.
  365.    */
  366.   return (i == argc);
  367. }
  368.  
  369.  
  370. /* set_defaults() gets called at xearth startup (before command line
  371.  * arguments are handled), regardless of what output mode (x, ppm,
  372.  * gif) is being used.
  373.  */
  374. void set_defaults()
  375. {
  376.   output_mode      = ModeX;
  377.   view_pos_type    = ViewPosTypeSun;
  378.   sun_rel_lat      = 0;
  379.   sun_rel_lon      = 0;
  380.   compute_sun_pos  = 1;
  381.   wdth             = 512;
  382.   hght             = 512;
  383.   shift_x          = 0;
  384.   shift_y          = 0;
  385.   view_mag         = 0.99;
  386.   do_shade         = 1;
  387.   do_label         = 0;
  388.   do_markers       = 1;
  389.   wait_time        = 300;
  390.   time_warp        = 1;
  391.   day              = 100;
  392.   night            = 10;
  393.   use_two_pixmaps  = 1;
  394.   num_colors       = 64;
  395.   do_fork          = 0;
  396.   priority         = 0;
  397.   do_stars         = 1;
  398.   star_freq        = 0.002;
  399.   do_grid          = 0;
  400.   grid_big         = 6;
  401.   grid_small       = 15;
  402.   fixed_time       = 0;
  403.   xgamma           = 1.0;
  404. }
  405.  
  406.  
  407. /* procedure for interpreting command line arguments when we're not
  408.  * using X; command_line_x() is used when we are.
  409.  */
  410. void command_line(argc, argv)
  411.      int   argc;
  412.      char *argv[];
  413. {
  414.   int i;
  415.  
  416.   progname = argv[0];
  417.  
  418.   for (i=1; i<argc; i++)
  419.   {
  420.     if (strcmp(argv[i], "-pos") == 0)
  421.     {
  422.       i += 1;
  423.       if (i >= argc) usage("missing arg to -pos");
  424.       decode_viewing_pos(argv[i]);
  425.     }
  426.     else if (strcmp(argv[i], "-sunpos") == 0)
  427.     {
  428.       i += 1;
  429.       if (i >= argc) usage("missing arg to -sunpos");
  430.       decode_sun_pos(argv[i]);
  431.     }
  432.     else if (strcmp(argv[i], "-mag") == 0)
  433.     {
  434.       i += 1;
  435.       if (i >= argc) usage("missing arg to -mag");
  436.       sscanf(argv[i], "%lf", &view_mag);
  437.       if (view_mag <= 0)
  438.         fatal("viewing magnification must be positive");
  439.     }
  440.     else if (strcmp(argv[i], "-size") == 0)
  441.     {
  442.       i += 1;
  443.       if (i >= argc) usage("missing arg to -size");
  444.       decode_size(argv[i]);
  445.     }
  446.     else if (strcmp(argv[i], "-shift") == 0)
  447.     {
  448.       i += 1;
  449.       if (i >= argc) usage("missing arg to -shift");
  450.       decode_shift(argv[i]);
  451.     }
  452.     else if (strcmp(argv[i], "-shade") == 0)
  453.     {
  454.       do_shade = 1;
  455.     }
  456.     else if (strcmp(argv[i], "-noshade") == 0)
  457.     {
  458.       do_shade = 0;
  459.     }
  460.     else if (strcmp(argv[i], "-label") == 0)
  461.     {
  462.       do_label = 1;
  463.       warning("labeling not supported with GIF and PPM output");
  464.     }
  465.     else if (strcmp(argv[i], "-nolabel") == 0)
  466.     {
  467.       do_label = 0;
  468.     }
  469.     else if (strcmp(argv[i], "-markers") == 0)
  470.     {
  471.       do_markers = 1;
  472.       warning("markers not supported with GIF and PPM output");
  473.     }
  474.     else if (strcmp(argv[i], "-nomarkers") == 0)
  475.     {
  476.       do_markers = 0;
  477.     }
  478.     else if (strcmp(argv[i], "-stars") == 0)
  479.     {
  480.       do_stars = 1;
  481.     }
  482.     else if (strcmp(argv[i], "-nostars") == 0)
  483.     {
  484.       do_stars = 0;
  485.     }
  486.     else if (strcmp(argv[i], "-starfreq") == 0)
  487.     {
  488.       i += 1;
  489.       if (i >= argc) usage("missing arg to -starfreq");
  490.       sscanf(argv[i], "%lf", &star_freq);
  491.       if ((star_freq < 0) || (star_freq > 1))
  492.     fatal("arg to -starfreq must be between 0 and 1");
  493.     }
  494.     else if (strcmp(argv[i], "-grid") == 0)
  495.     {
  496.       do_grid = 1;
  497.     }
  498.     else if (strcmp(argv[i], "-nogrid") == 0)
  499.     {
  500.       do_grid = 0;
  501.     }
  502.     else if (strcmp(argv[i], "-grid1") == 0)
  503.     {
  504.       i += 1;
  505.       if (i >= argc) usage("missing arg to -grid1");
  506.       sscanf(argv[i], "%d", &grid_big);
  507.       if (grid_big <= 0)
  508.     fatal("arg to -grid1 must be positive");
  509.     }
  510.     else if (strcmp(argv[i], "-grid2") == 0)
  511.     {
  512.       i += 1;
  513.       if (i >= argc) usage("missing arg to -grid2");
  514.       sscanf(argv[i], "%d", &grid_small);
  515.       if (grid_small <= 0)
  516.     fatal("arg to -grid2 must be positive");
  517.     }
  518.     else if (strcmp(argv[i], "-day") == 0)
  519.     {
  520.       i += 1;
  521.       if (i >= argc) usage("missing arg to -day");
  522.       sscanf(argv[i], "%d", &day);
  523.       if ((day > 100) || (day < 0))
  524.         fatal("arg to -day must be between 0 and 100");
  525.     }
  526.     else if (strcmp(argv[i], "-night") == 0)
  527.     {
  528.       i += 1;
  529.       if (i >= argc) usage("missing arg to -night");
  530.       sscanf(argv[i], "%d", &night);
  531.       if ((night > 100) || (night < 0))
  532.         fatal("arg to -night must be between 0 and 100");
  533.     }
  534.     else if (strcmp(argv[i], "-gamma") == 0)
  535.     {
  536.       i += 1;
  537.       if (i >= argc) usage("missing arg to -gamma");
  538.       sscanf(argv[i], "%lf", &xgamma);
  539.       if (xgamma <= 0)
  540.         fatal("arg to -gamma must be positive");
  541.       warning("gamma correction not supported with GIF and PPM output");
  542.     }
  543.     else if (strcmp(argv[i], "-wait") == 0)
  544.     {
  545.       i += 1;
  546.       if (i >= argc) usage("missing arg to -wait");
  547.       sscanf(argv[i], "%d", &wait_time);
  548.       if (wait_time < 0)
  549.         fatal("arg to -wait must be non-negative");
  550.     }
  551.     else if (strcmp(argv[i], "-timewarp") == 0)
  552.     {
  553.       i += 1;
  554.       if (i >= argc) usage("missing arg to -timewarp");
  555.       sscanf(argv[i], "%lf", &time_warp);
  556.       if (time_warp <= 0)
  557.     fatal("arg to -timewarp must be positive");
  558.     }
  559.     else if (strcmp(argv[i], "-time") == 0)
  560.     {
  561.       i += 1;
  562.       if (i >= argc) usage("missing arg to -time");
  563.       sscanf(argv[i], "%d", &fixed_time);
  564.     }
  565.     else if (strcmp(argv[i], "-onepix") == 0)
  566.     {
  567.       use_two_pixmaps = 0;
  568.       warning("-onepix not relevant for GIF or PPM output");
  569.     }
  570.     else if (strcmp(argv[i], "-twopix") == 0)
  571.     {
  572.       use_two_pixmaps = 1;
  573.       warning("-twopix not relevant for GIF or PPM output");
  574.     }
  575.     else if (strcmp(argv[i], "-mono") == 0)
  576.     {
  577.       warning("monochrome mode not supported with GIF and PPM output");
  578.     }
  579.     else if (strcmp(argv[i], "-nomono") == 0)
  580.     {
  581.       warning("monochrome mode not supported with GIF and PPM output");
  582.     }
  583.     else if (strcmp(argv[i], "-ncolors") == 0)
  584.     {
  585.       i += 1;
  586.       if (i >= argc) usage("missing arg to -ncolors");
  587.       sscanf(argv[i], "%d", &num_colors);
  588.       if (num_colors < 3)
  589.         fatal("arg to -ncolors must be >= 3");
  590.     }
  591.     else if (strcmp(argv[i], "-font") == 0)
  592.     {
  593.       i += 1;
  594.       if (i >= argc) usage("missing arg to -font");
  595.       warning("-font not relevant for GIF or PPM output");
  596.     }
  597.     else if (strcmp(argv[i], "-fork") == 0)
  598.     {
  599.       do_fork = 1;
  600.     }
  601.     else if (strcmp(argv[i], "-nofork") == 0)
  602.     {
  603.       do_fork = 0;
  604.     }
  605.     else if (strcmp(argv[i], "-nice") == 0)
  606.     {
  607.       i += 1;
  608.       if (i >= argc) usage("missing arg to -nice");
  609.       sscanf(argv[i], "%d", &priority);
  610.     }
  611.     else if (strcmp(argv[i], "-version") == 0)
  612.     {
  613.       version_info();
  614.     }
  615.     else if (strcmp(argv[i], "-ppm") == 0)
  616.     {
  617.       output_mode = ModePPM;
  618.     }
  619.     else if (strcmp(argv[i], "-gif") == 0)
  620.     {
  621.       output_mode = ModeGIF;
  622.     }
  623.     else if (strcmp(argv[i], "-display") == 0)
  624.     {
  625.       fatal("-display not compatible with -ppm or -gif\n");
  626.     }
  627.     else
  628.     {
  629.       usage(NULL);
  630.     }
  631.   }
  632. }
  633.  
  634.  
  635. static char **tokenize(s, delim, argc_ret)
  636.      char *s;
  637.      char *delim;
  638.      int  *argc_ret;
  639. {
  640.   int    flag;
  641.   int    lim;
  642.   int    argc;
  643.   char **argv;
  644.  
  645.   lim  = 4;
  646.   argc = 0;
  647.   argv = (char **) malloc((unsigned) sizeof(char *) * lim);
  648.   assert(argv != NULL);
  649.  
  650.   flag = 1;
  651.  
  652.   while (1)
  653.   {
  654.     if (*s == '\0')
  655.     {
  656.       break;
  657.     }
  658.     else if (strchr(delim, *s) != NULL)
  659.     {
  660.       *s = '\0';
  661.       flag = 1;
  662.     }
  663.     else if (flag)
  664.     {
  665.       if (argc == lim)
  666.       {
  667.     lim *= 2;
  668.     argv = (char **) realloc(argv, (unsigned) sizeof(char *) * lim);
  669.     assert(argv != NULL);
  670.       }
  671.       argv[argc++] = s;
  672.       flag = 0;
  673.     }
  674.  
  675.     s += 1;
  676.   }
  677.  
  678.   *argc_ret = argc;
  679.   return argv;
  680. }
  681.  
  682.  
  683. /* decode viewing position specifier; three possibilities:
  684.  *
  685.  *  fixed lat lon  - viewing position fixed wrt earth at (lat, lon)
  686.  *
  687.  *  sunrel lat lon - viewing position fixed wrt sun at (lat, lon)
  688.  *                   [position interpreted as if sun was at (0, 0)]
  689.  *
  690.  *  orbit per inc  - moving viewing position following simple orbit
  691.  *                   with period per and inclination inc
  692.  *
  693.  * fields can be separated with either spaces, commas, or slashes.
  694.  */
  695. void decode_viewing_pos(s)
  696.      char *s;
  697. {
  698.   int    argc;
  699.   char **argv;
  700.   double arg1;
  701.   double arg2;
  702.  
  703.   argv = tokenize(s, " ,/", &argc);
  704.   if (argc != 3)
  705.     fatal("wrong number of args in viewing position specifier");
  706.  
  707.   arg1 = 0;
  708.   arg2 = 0;
  709.   sscanf(argv[1], "%lf", &arg1);
  710.   sscanf(argv[2], "%lf", &arg2);
  711.  
  712.   if (strcmp(argv[0], "fixed") == 0)
  713.   {
  714.     view_lat      = arg1;
  715.     view_lon      = arg2;
  716.     view_pos_type = ViewPosTypeFixed;
  717.  
  718.     if ((view_lat > 90) || (view_lat < -90))
  719.       fatal("viewing latitude must be between -90 and 90");
  720.     if ((view_lon > 180) || (view_lon < -180))
  721.       fatal("viewing longitude must be between -180 and 180");
  722.   }
  723.   else if (strcmp(argv[0], "sunrel") == 0)
  724.   {
  725.     sun_rel_lat   = arg1;
  726.     sun_rel_lon   = arg2;
  727.     view_pos_type = ViewPosTypeSun;
  728.  
  729.     if ((sun_rel_lat > 90) || (sun_rel_lat < -90))
  730.       fatal("latitude relative to sun must be between -90 and 90");
  731.     if ((sun_rel_lon > 180) || (sun_rel_lon < -180))
  732.       fatal("longitude relative to sun must be between -180 and 180");
  733.   }
  734.   else if (strcmp(argv[0], "orbit") == 0)
  735.   {
  736.     orbit_period  = arg1 * 3600;
  737.     orbit_inclin  = arg2;
  738.     view_pos_type = ViewPosTypeOrbit;
  739.  
  740.     if (orbit_period <= 0)
  741.       fatal("orbital period must be positive");
  742.     if ((orbit_inclin > 90) || (orbit_inclin < -90))
  743.       fatal("orbital inclination must be between -90 and 90");
  744.   }
  745.   else
  746.   {
  747.     fprintf(stderr, "`%s'\n", argv[0]);
  748.     fatal("unrecognized keyword in viewing position specifier");
  749.   }
  750.  
  751.   free(argv);
  752. }
  753.  
  754.  
  755. /* decode sun position specifier:
  756.  *
  757.  *  lat lon - sun position fixed wrt earth at (lat, lon)
  758.  *
  759.  * fields can be separated with either spaces, commas, or slashes.
  760.  */
  761. void decode_sun_pos(s)
  762.      char *s;
  763. {
  764.   int    argc;
  765.   char **argv;
  766.  
  767.   argv = tokenize(s, " ,/", &argc);
  768.   if (argc != 2)
  769.     fatal("wrong number of args in sun position specifier");
  770.  
  771.   sscanf(argv[0], "%lf", &sun_lat);
  772.   sscanf(argv[1], "%lf", &sun_lon);
  773.  
  774.   if ((sun_lat > 90) || (sun_lat < -90))
  775.     fatal("sun latitude must be between -90 and 90");
  776.   if ((sun_lon > 180) || (sun_lon < -180))
  777.     fatal("sun longitude must be between -180 and 180");
  778.  
  779.   compute_sun_pos = 0;
  780.  
  781.   free(argv);
  782. }
  783.  
  784.  
  785. /* decode size specifier:
  786.  *
  787.  *  width height - width and height of image (in pixels)
  788.  *
  789.  * fields can be separated with either spaces, commas, or slashes.
  790.  */
  791. void decode_size(s)
  792.      char *s;
  793. {
  794.   int    argc;
  795.   char **argv;
  796.  
  797.   argv = tokenize(s, " ,/", &argc);
  798.   if (argc != 2)
  799.     fatal("wrong number of args in size specifier");
  800.  
  801.   sscanf(argv[0], "%d", &wdth);
  802.   sscanf(argv[1], "%d", &hght);
  803.  
  804.   if (wdth <= 0)
  805.     fatal("wdth arg must be positive");
  806.   if (hght <= 0)
  807.     fatal("hght arg must be positive");
  808.  
  809.   free(argv);
  810. }
  811.  
  812.  
  813. /* decode shift specifier:
  814.  *
  815.  *  xofs yofs - offset in x and y dimensions
  816.  *
  817.  * fields can be separated with either spaces, commas, or slashes.
  818.  */
  819. void decode_shift(s)
  820.      char *s;
  821. {
  822.   int    argc;
  823.   char **argv;
  824.  
  825.   argv = tokenize(s, " ,/", &argc);
  826.   if (argc != 2)
  827.     fatal("wrong number of args in size specifier");
  828.  
  829.   sscanf(argv[0], "%d", &shift_x);
  830.   sscanf(argv[1], "%d", &shift_y);
  831.  
  832.   free(argv);
  833. }
  834.  
  835.  
  836. void xearth_bzero(buf, len)
  837.      char *buf;
  838.      int   len;
  839. {
  840.   int *tmp;
  841.  
  842.   /* assume sizeof(int) is a power of two
  843.    */
  844.   assert((sizeof(int) == 4) || (sizeof(int) == 8));
  845.  
  846.   if (len < sizeof(int))
  847.   {
  848.     /* special case small regions
  849.      */
  850.     while (len > 0)
  851.     {
  852.       *buf = 0;
  853.       buf += 1;
  854.       len -= 1;
  855.     }
  856.   }
  857.   else
  858.   {
  859.     /* zero leading non-word-aligned bytes
  860.      */
  861.     while (((long) buf) & (sizeof(int)-1))
  862.     {
  863.       *buf = 0;
  864.       buf += 1;
  865.       len -= 1;
  866.     }
  867.  
  868.     /* zero trailing non-word-aligned bytes
  869.      */
  870.     while (len & (sizeof(int)-1))
  871.     {
  872.       len     -= 1;
  873.       buf[len] = 0;
  874.     }
  875.  
  876.     /* convert remaining len to words
  877.      */
  878.     tmp = (int *) buf;
  879.     if (sizeof(int) == 4)
  880.       len >>= 2;
  881.     else if (sizeof(int) == 8)
  882.       len >>= 3;
  883.     else
  884.       assert(0);
  885.  
  886.     /* zero trailing non-quadword-aligned words
  887.      */
  888.     while (len & 0x03)
  889.     {
  890.       len     -= 1;
  891.       tmp[len] = 0;
  892.     }
  893.  
  894.     /* zero remaining data four words at a time
  895.      */
  896.     while (len)
  897.     {
  898.       tmp[0] = 0;
  899.       tmp[1] = 0;
  900.       tmp[2] = 0;
  901.       tmp[3] = 0;
  902.       tmp += 4;
  903.       len -= 4;
  904.     }
  905.   }
  906. }
  907.  
  908.  
  909. void version_info()
  910. {
  911.   fflush(stdout);
  912.   fprintf(stderr, "\nThis is xearth version %s.\n\n", VersionString);
  913.   exit(0);
  914. }
  915.  
  916.  
  917. void usage(msg)
  918.      char *msg;
  919. {
  920.   fflush(stdout);
  921.   fprintf(stderr, "\n");
  922.   if (msg != NULL)
  923.     fprintf(stderr, "%s\n", msg);
  924.   fprintf(stderr, "usage: %s\n", progname);
  925.   fprintf(stderr, " [-pos pos_spec] [-sunpos sun_pos_spec] [-mag factor]\n");
  926.   fprintf(stderr, " [-size size_spec] [-shift shift_spec] [-shade|-noshade]\n");
  927.   fprintf(stderr, " [-label|-nolabel] [-markers|-nomarkers] [-stars|-nostars]\n");
  928.   fprintf(stderr, " [-starfreq frequency] [-grid|-nogrid] [-grid1 grid1] [-grid2 grid2]\n");
  929.   fprintf(stderr, " [-day pct] [-night pct] [-gamma gamma_value] [-wait secs]\n");
  930.   fprintf(stderr, " [-timewarp timewarp_factor] [-time fixed_time] [-onepix|-twopix]\n");
  931.   fprintf(stderr, " [-mono|-nomono] [-ncolors num_colors] [-font font_name]\n");
  932.   fprintf(stderr, " [-fork|-nofork] [-nice priority] [-gif] [-ppm] [-display dpyname]\n");
  933.   fprintf(stderr, " [-version]\n");
  934.   fprintf(stderr, "\n");
  935.   exit(1);
  936. }
  937.  
  938.  
  939. void warning(msg)
  940.      char *msg;
  941. {
  942.   fflush(stdout);
  943.   fprintf(stderr, "\n%s: warning - %s\n", progname, msg);
  944.   fflush(stderr);
  945. }
  946.  
  947.  
  948. void fatal(msg)
  949.      char *msg;
  950. {
  951.   fflush(stdout);
  952.   fprintf(stderr, "\n%s: fatal - %s\n", progname, msg);
  953.   fprintf(stderr, "\n");
  954.   exit(1);
  955. }
  956.